<?php
/**
 * Copyright (c) 2006, PORTALIER Julien
 *
 * Licensed under The LGPL License
 * Redistributions of files must retain the above copyright notice.
 *
 * @package      FeatherCMS
 * @subpackage   Members
 * @copyright    Copyright (c) 2006, Julien PORTALIER
 * @link         http://julien.portalier.com
 * @license      http://www.opensource.org/licenses/lgpl-license.php The LGPL License
 * 
 * @todo Unactivated accounts should be erased after a certain period of time.
 */

class MembersController extends Controller
{
	public $module     = 'member';
	public $_templates = 'members';
	
	protected $restrictedAccess = array('edit', 'profile', 'avatar', 'my', 'live');
	
	// overrides
	
	function beforeAction()
	{
		if (in_array($this->action, $this->restrictedAccess))
		{
			if (!$this->acl->identified)
				$this->acl->permissionDenied();
		}
		return true;
	}
	
	// auth
	
	function login()
	{
		if (isPost())
		{
			$ret = $this->__login();
			
			if ($ret === true)
			{
				// logged in
				
				if (!empty($this->params['forum']['referer']))
				{
					// referer isn't a page we shouldn't return to?
					if (!preg_match(':/members/(resend|activate|register|reminder|login|logout):', $this->params['forum']['referer']))
						$referer = $this->params['forum']['referer'];
				}
				
				// redirects
				$this->flash(s_("Welcome in, %s.", $this->acl->id), isset($referer) ? $referer : '/members/my');
			}
			elseif ($ret === null)
			{
				// unactivated account
				$this->render('unactivated');
			}
			else {
#				$this->session->setFlash(_("Error: unknown login or wrong password. Please verify typing mistakes."));
				$this->set('login_error', _("Error: unknown username or wrong password. Please verify typing mistakes."));
			}
			/*
			switch($this->__login())
			{
				case true:
					// logged in
					$this->flash(s_("Welcome in, %s.", $this->acl->id),
						empty($this->params['form']['referer']) ? '/members/my' : $this->params['form']['referer']);
					break;
				
				case null:
					// unactivated account
					$this->render('unactivated');
					break;
				
				default:
					$this->Session->setFlash(_("Error: unknown login or wrong password. Please verify typing mistakes."));
			}
			*/
		}
		
		$this->pageTitle = _('Login');
	}
	
	function logout()
	{
		$this->acl->logout();
		$this->flash(_("You've been logged out."),
			isset($this->params['form']['referer']) ? $this->params['form']['referer'] : '/');
	}
	
	// registration
	
	function register()
	{
		if (empty($this->data))
			$this->data['Member']['hide_email'] = true;
		elseif ($this->Member->save(null, true, 'insert'))
		{
			// informs member
			$this->load->components('swift');
			$this->swift->addRecipient($this->data['Member']['email'], $this->data['Member']['id']);
			$this->swift->send(_('Your account has been created'), array(Config::website_email, Config::website_name));
			
			$this->message(_("You account has been created!"),
				_("Welcome aboard! Your account has been created and just need to be activated. An email with the link to follow has just been sent to your email address. It should arrive soon!"));
		}
		
		$this->data['Member']['pwd'] = '';
		$this->data['Member']['pwd2'] = '';
		$this->pageTitle = _('Member registration');
	}
	
	function activate($id, $activate)
	{
		$this->Member->recursive = 0;
		$user = $this->Member->read('id, email, activate');
		
		if (!empty($user))
		{
			if (!empty($activate) and $user['Member']['activate'] == $activate)
			{
				// activates account
				$this->Member->saveField('activate', '-! NULL', false);
				
				// groups
				/*
				foreach(explode(' ', Config::default_groups) as $grp)
				{
					$this->Member->Group->register($id, $grp);
					$user['Member']['groups'][] = $grp;
				}
				*/
				$this->Member->Group->register($id, 'member');
				$user['Member']['groups'][] = 'member';
				
				// creates ARO
				$this->acl->Perms->Aro->create("User.$id");
				
				// logs member in
				$this->acl->login(&$user['Member']);
				
				copy(WWW_ROOT.'img/noavatar.jpg', WWW_ROOT.'files/icons/avatars/'.strtolower($id).'.jpg');
				
				// informs member
				$this->load->components('swift');
				/*
				$this->swift->connect();
				$this->swift->send(
					array(array($user['Member']['id'], $user['Member']['email'])),
					Config::website_email,
					_('Your account has been activated')
				);
				*/
				$this->swift->addRecipient($user['Member']['email'], $user['Member']['id']);
				$this->swift->send(_('Your account has been activated'), array(Config::website_email, Config::website_name));
				
				// redirects to my page
				$this->flash(_('Your account has been activated!'), '/members/my');
			}
			$this->flash(_("Error: invalid activation link."), '/members/resend');
		}
		$this->flash(_("Error: there is no such account."), '/');
	}
	
	function resend()
	{
		if (isset($this->params['url']['q']))
		{
			$q = $this->params['url']['q'];
			
			// looks for an account
			$this->Member->recursive = -1;
			$this->Member->conditions(array('email' => $q, 'id' => $q));
			$this->Member->operator('OR');
			$user = $this->Member->find('id, email, activate');
			
			if (!empty($user))
			{
				$this->set('user', &$user);
				
				// resends activation link
				$this->load->components('swift');
				/*
				$this->swift->connect();
				$this->swift->send(
					array(array($user['Member']['id'], $user['Member']['email'])),
					Config::website_email,
					_('Your activation link')
				);
				*/
				$this->swift->addRecipient($user['Member']['email'], $user['Member']['id']);
				$this->swift->send(_('Your activation link'), array(Config::website_email, Config::website_name));
				
				$this->message(_("Activation link sent."),
					_('Your activation link has been sent to your email address. It should arrive soon.'));
			}
			else {
				$this->session->setFlash(_("Error: there is no such account."));
			}
		}
		
		$this->pageTitle = _('Resend activation link');
	}
	
	function reminder()
	{
		if (isset($this->params['url']['q']))
		{
			$q = $this->params['url']['q'];
			
			// looks for an account
			$this->Member->recursive = -1;
			$this->Member->conditions(array('email' => $q, 'id' => $q));
			$this->Member->operator('OR');
			$user = $this->Member->find('id, email, activate');
			
			if (!empty($user))
			{
				// generates new password
				$user['Member']['pwd'] = substr(md5(mt_rand()), 0, 8);
				$cpwd = $this->Member->__cryptPwd($user['Member']['pwd']);
				$data['salt'] = $cpwd[0];
				$data['pwd']  = $cpwd[1];
				
				// saves password
				$this->Member->id = $user['Member']['id'];
				if ($this->Member->saveFields(&$data))
				{
					$this->set('user', &$user['Member']);
					
					// sends new password
					$this->load->components('swift');
					/*
					$this->swift->connect();
					$this->swift->send(
						array(array($user['Member']['id'], $user['Member']['email'])),
						Config::website_email,
						_('Your new password')
					);
					*/
					$this->swift->addRecipient($user['Member']['email'], $user['Member']['id']);
					$this->swift->send(_('Your new password'), array(Config::website_email, Config::website_name));
					
					$this->message(_("New password sent!"),
						_("Your new password has been sent to your email address. It should arrive soon."));
				}
				else {
					$this->session->setFlash(_("Oops, an error occured."));
				}
			}
			else {
				$this->session->setFlash(_("Error: there is no such account."));
			}
		}
		$this->pageTitle = _('Password reminder');
	}
	
	// edition
	
	/** @todo Check for new email realness before changing it! */
	function edit()
	{
		$this->Member->id = $this->acl->id;
		$this->Member->recursive = -1;
		
		if (empty($this->data))
			$this->data = $this->Member->read();
		else
		{
			if (empty($this->data['Member']['pwd']) and empty($this->data['Member']['pwd2']))
			{
				unset($this->data['Member']['old_pwd']);
				unset($this->data['Member']['pwd']);
				unset($this->data['Member']['pwd2']);
			}
			
			if ($this->Member->save())
				$this->flash(_("Your account has been updated."), '/members/my');
		}
		
		unset($this->data['Member']['pwd']);
		unset($this->data['Member']['old_pwd']);
		unset($this->data['Member']['pwd']);
		unset($this->data['Member']['pwd2']);
		
		$this->pageTitle = _('Account edition');
	}
	
	function profile()
	{
		$this->Member->id = $this->acl->id;
		$this->Member->recursive = -1;
		
		if (empty($this->data))
			$this->data = $this->Member->read();
		elseif ($this->Member->save())
			$this->flash(_("Your profile has been updated."), '/members/my');
		
		$this->pageTitle = _('Profile edition');
	}	
	
	function avatar()
	{
		if (isPost())
		{
			$this->load->libs('file_upload');
			$upload = new FileUpload();
			
			// saves uploaded avatar
			if ($upload->check('avatar'))
			{
				$tmp = $upload->getTmpFilename('avatar');
				$mime = mime_content_type($tmp);
				
				if (preg_match(':image/(jpeg|png|gif):', $mime))
				{
					$avatar = WWW_ROOT.'/files/icons/avatars/'.strtolower($this->acl->id).'.jpg';
					
					$this->load->libs('resampler');
					$resampler = new Resampler();
					$resampler->load($tmp);
					
					// saves or resamples avatar
					if (preg_match(':image/jpeg:', $mime)
						and $resampler->size[0] == 50
						and $resampler->size[1] == 50)
					{
						$upload->save('avatar', $avatar);
					}
					else
					{
						$resampler->create($avatar, 50, 50, true);
					}
					
					$this->flash(_("Your avatar has been uploaded and should appear in a moment. If you're in a hurry to see it, you may simply reload this page or empty your browser's cache."), '/members/my');
				}
				else {
					$this->session->setFlash(_("Error: uploaded avatar was not a JPEG, PNG or GIF file."));
				}
			}
		}
		
		$this->pageTitle = _("Upload an avatar");
	}
	
	// display
	
	function my()
	{
		$this->show($this->acl->id);
		$this->pageTitle = _('My page');
	}
	
	function show($id)
	{
		$this->data = $this->Member->read('*', $id);
		
		if (empty($this->data))
			Error::show(404);
		
		$this->pageTitle = $this->data['Member']['id'];
	}
	
	function live($q)
	{
#		$fname = 'live'.DS.'members-'.md5($q);
#		$this->data = cache($fname, null, '+10 minutes');
#		if (is_null($this->data))
#		{
			$this->Member->conditions(array('Group.name' => '<> Anonymous', 'Member.id' => "LIKE $q%"));
			$this->Member->bind(array('hasOne' => 'Group'));
			$this->data = $this->Member->listField('Member.id');
#			cache('live'.DS.'members-'.md5($q), serialize($this->data), '+10 minutes');
#		}
#		else {
#			$this->data = unserialize($this->data);
#		}
		$this->layout = 'bare';
	}
	
	// admin
	
	function index()
	{
		if (!$this->acl->inGroup(Config::admins))
			$this->acl->permissionDenied();
		
		$url =& $this->params['url'];
		
		// conditions
		$conditions = array('Member.id' => array("<> Anonymous"));
		if (isset($url['q']))
			$conditions['Member.id'][] = "LIKE {$url['q']}%";
		
		$this->Member->conditions(&$conditions);
		
		// pagination
		$paging = array(
			'page'  => isset($url['page']) ? $url['page'] : 1,
			'count' => $this->Member->findCount(0, false),
			'limit' => 25,
			'link'  => '/members?'.(isset($url['q']) ? 'q='.$url['q'].'&amp;' : '').'page=',
		);
		$this->set('paging', &$paging);
		$this->load->helpers('pagination');
		
		// members
		$this->Member->order('Member.id ASC');
		$this->data = $this->Member->findAll('*', $paging['limit'], $paging['page']);
		
		$this->pageTitle = _('Members');
	}
	
	/*
	function ban($member_id)
	{
		if (!$this->acl->inGroup(Config::admins))
			$this->acl->permissionDenied();
		
		if ($this->Member->ban($member_id, true))
		{
			// informs member
			
#			(...)
			
			$this->session->setFlash(_("Member has been banned."));
		}
		else
			$this->session->setFlash(_("An error occured."));
		$this->redirect(getReferer());
	}
	*/
	/*
	function unban($member_id)
	{
		if (!$this->acl->inGroup(Config::admins))
			$this->acl->permissionDenied();
		
		if ($this->Member->ban($member_id, false))
		{
			// informs member
			
#			(...)
			
			$this->session->setFlash(_("Member is no longer banned."));
		}
		else
			$this->session->setFlash(_("An error occured."));
		$this->redirect(getReferer());
	}
	*/
	
	// internals
	
	protected function __login()
	{
		$form =& $this->params['form'];
		
		if (isset($form['uid']) and isset($form['pwd']))
		{
			$user =& $this->Member->login($form['uid'], $form['pwd']);
			if ($user)
			{
				$user['pwd'] = $form['pwd'];
				$this->acl->login(&$user, isset($form['remember']));
				return true;
			}
			return $user;
		}
	}
}
?>